﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net.Sockets;
using System.Net;
using System.IO;

namespace Model
{
    public class ClientHandler
    {
        Socket clientSocket;
        AktuelleAuktion aktuelAuktion;

        
        NetworkStream netStream;
        StreamReader reader;
        StreamWriter writer;

        private object commandLock = new object(); // Lås

        private bool clientforbundet = false;

        public ClientHandler(Socket clientSocket, AktuelleAuktion aktuelAuktion)
        {
            this.clientSocket = clientSocket;
            this.aktuelAuktion = aktuelAuktion;
        }

        public void RunClient()
        {
                
                // Streams der bruges til at transportere kaldende til/fra server og klient.
                netStream = new NetworkStream(clientSocket);
                reader= new StreamReader(netStream);
                writer= new StreamWriter(netStream);
                
                clientforbundet = true;
                
                // Test til forbindelse i Telnet.
                writer.WriteLine("Velkommen til test");
                writer.Flush();
                
                // Tilføjelse af de forskellige broadcast til klienterne.
                aktuelAuktion.afgivbudEvent+=Sendbeskedklient;
                aktuelAuktion.broadcastEvent += Sendbeskedklient;
                aktuelAuktion.IngenAuktionerEvent+= Sendbeskedklient;
                
                string commando;
                
                // Løkke som venter på kommandoer fra klienten, når der er en klient forbundet.
                while (clientforbundet)
                {
                    // Serveren venter på en kommando.
                    commando = reader.ReadLine();

                    string[] data = { "" };

                    // Kommandoen splittes op i et array på "mellemrum", og sætter den til små bogstaver.
                    if (commando != null)
                    data = commando.ToLower().Split(' ');

                    // Her kigger switch'en på den første plads i arrayet, om den er en af de nedenstående cases.
                    switch (data[0])
                    {
                            // Når serveren modtager kommandoen auktion, sendes den igangværende auktion til klienten.
                        case "auktion":
                            SendAktuelAuktion();
                            break;

                            //Bud sender en string fra klienten, som indeholder kommandoen, et beløb på plads 2[1] og et brugernavn[2]
                        case "bud":
                            aktuelAuktion.AfgivBud(int.Parse(data[1]), data[2]);
                            writer.WriteLine("Budmodtaget"); // Kun til konsol test.
                            writer.Flush();
                            break;

                            // Sender de vundne auktioner på det enkelte brugernavn.
                        case "vundne":
                            //aktuelAuktion.GetVundneAuktioner(data[1]);
                            break;

                            //Viser de kommende auktioner.
                        case "kommende":
                            SendKommendeAuktioner();
                            break;
                            // I tilfælde af tom eller forkert kommando
                        default:
                            break;

                    }
                }
                
                // Skulle lukke forbindelse, men server bliver lagt ned når klienten lukkes (Ikke rette endnu).
                writer.Close();
                reader.Close();
                netStream.Close();
                clientSocket.Close();
        }

        // Metoden går igennem en liste med auktioner, og for hver af disse skriver den auktionen til klienten.
        public void SendKommendeAuktioner()
        {
            foreach (string auktion in aktuelAuktion.AuktionerString)
            {
                writer.WriteLine(auktion);
                Writer.Flush();
            }
        }

        // Finder det aktuelle auktionsobjekt og laver en string, der sendes til klienten med "#" separering.
        public void SendAktuelAuktion()
        {
            Auktion akauktion = aktuelAuktion.GetAktuelAuktion();

            string auktion = akauktion.Navn + "#" + akauktion.HøjestePris + "#" + akauktion.Beskrivelse;

            writer.WriteLine(auktion);
            writer.Flush();
        }

        // Metoden bliver tilsluttet vores delegates.
        public void Sendbeskedklient(string besked)
        {
            writer.WriteLine(besked);
            writer.Flush();
        }

        // Properties er blevet locked.
        #region *** Properties ***

        public StreamReader Reader
        {
            get { lock(commandLock) return reader; }
        }

        public StreamWriter Writer
        {
            get { lock(commandLock) return writer; }
        }

        #endregion
    }
}
